package com.fdb.efp.nls.service.impl.bd;

import com.fdb.basic.framework.core.base.FrameworkService;
import com.fdb.basic.framework.core.exception.ESBException;
import com.fdb.basic.framework.core.util.TimeUtil;
import com.fdb.efp.nls.common.ImageBizConstant;
import com.fdb.efp.nls.service.vo.ImageBizDetailVO;
import com.fdb.efp.nls.service.vo.ImageBizInfoVO;
import com.fdb.efp.nls.service.facade.ImageBizDetailService;
import com.fdb.efp.nls.service.facade.ImageBizInfoService;
import com.fdb.efp.nls.service.facade.bd.DownloadBaiduFileService;
import com.fdb.efp.esb.common.constant.dxm.reqbuilder.DXMBasicInfo;
import com.fdb.efp.esb.service.bo.req.dxm.ReqGetImageFileBean;
import com.fdb.efp.esb.service.bo.resp.dxm.RespGetImageFileBean;
import com.fdb.efp.esb.service.facade.dxm.GetImageFileService;
import com.fdb.efp.nls.service.facade.NlsApplyInfoService;
import com.fdb.efp.nls.service.facade.sx.NlsCreditInfoService;
import com.fdb.efp.nls.service.vo.NlsApplyInfoVO;
import com.fdb.efp.nls.service.vo.sx.NlsCreditInfoVO;
import com.sunyard.client2.FileNameEnums;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.io.IOException;
import java.util.*;

import static com.fdb.efp.nls.common.ImageBizConstant.*;


/**
 * 从百度获取申请人身份证正面，反面，活体照片: <br>
 * <p>
 * 0.1:caoxin:2019/3/25 11:19: 从百度获取申请人身份证正面，反面，活体照片: <br>
 *
 * @author caoxin
 * @version 0.1
 * @date 2019/3/25 11:19
 * @since 2019/3/25 11:19
 */
@Service("downloadBaiduFileService")
public class DownloadBaiduFileServiceImpl implements DownloadBaiduFileService, FrameworkService {

    private Logger logger = LoggerFactory.getLogger(DownloadBaiduFileServiceImpl.class);

    /** 调用百度接口后去对应的身份证正反面，活体照服务*/

    @Autowired
    private GetImageFileService getImageFileService;

    /** 放款申请信息流水服务*/
    @Autowired
    private NlsApplyInfoService nlsApplyInfoService;

    @Autowired
    private NlsCreditInfoService nlsCreditInfoService;

    /** 影像业务信息*/
    @Autowired
    private ImageBizInfoService imageBizInfoService;

    /** 影像业务信息明细*/
    @Autowired
    private ImageBizDetailService imageBizDetailService;

    /** 影像业务文件路径*/
    @Value("${analysis.baidu.archImageFilePath}")

    private String IMG_PATH;

    /** 文件路径前缀*/
    private static final String FILE_PATH = "bdFileTemp/";


    /** 照片类型*/
    private static final String ID_PICTURE0 = "0";
    private static final String ID_PICTURE1 = "1";
    private static final String ID_LIVING_PRITURE = "2";

    /** 日志模板*/
    private static String MSG_TEMPLATE = "message{ }";
    /** 照片状态已获取*/
    private static final String GET_PHOTO = "2";

    /** 照片分隔符*/
    private static final String ImageFileSeparator = "_";
    /** 照片分隔符*/
    private static final String ImageFileSuffix = ".jpeg";
    /** 文件描述映射*/
    private static final Map<String,String> fileDescMap = new HashMap<>();
    static {
        fileDescMap.put(ID_PICTURE0,"身份证正面照");
        fileDescMap.put(ID_PICTURE1,"身份证反面照");
        fileDescMap.put(ID_LIVING_PRITURE,"人像活体照");
    }

    /**
     * 从百度获取申请人身份证正面，反面，活体照片: <br>
     * <p>
     * 0.1:caoxin:2019/3/26 17:32: TODO: <br>
     *
     * @return
     * @author caoxin
     * @date 2019/3/26 17:32
     * @version 0.1
     * @since 2019/3/26 17:32
     */
    @Override
    public void downloadBaiduFile() {
        String message = "=======>获取百度的照片定时调度开始<======";
        logger.info(message,MSG_TEMPLATE);
        // 获取放款申请信息流水服务中，未获取图片信息的用户 每次只查1000条
        // 先查出来有多少条数据
        double totalSize = nlsApplyInfoService.queryCountByBdIdPictureState();
        if (totalSize <= 0) {
            logger.info("=======>没有需要获取百度的照片<======", MSG_TEMPLATE);
            return;
        }
        // 按每次处理1000条的标准计算需要循环的次数
        double pageSize = 1000;
        double ceil = Math.ceil(totalSize / pageSize);
        for (int i = 0; i <= ceil; i++) {
                handler();
        }
        logger.info("=======>获取百度的照片定时调度结束<======");
    }

    /**
     * 每次查询1000条数据进行处理
     */
    private void handler() {
        List<NlsApplyInfoVO> nlsApplyInfoVOS = nlsApplyInfoService.queryListByBdIdPictureState();
        for (NlsApplyInfoVO nlsApplyInfoVO : nlsApplyInfoVOS) {
            if (Objects.isNull(nlsApplyInfoVO.getBdIdpicture0()) || Objects.isNull(nlsApplyInfoVO.getBdIdpicture1()) || Objects.isNull(nlsApplyInfoVO.getBdLivingPhoto())){
                continue;
            }
            // 基本信息
            DXMBasicInfo basicInfo = new DXMBasicInfo();
            basicInfo.setIDCertNo(nlsApplyInfoVO.getCertCode());
            basicInfo.setBankCardNo(nlsApplyInfoVO.getRecvAcctNo());
            basicInfo.setCustNm(nlsApplyInfoVO.getCusName());
            basicInfo.setMblNo(nlsApplyInfoVO.getMobile());
            byte[] idpicture0 = null;
            byte[] idpicture1 = null;
            byte[] livingPicture = null;
            // 获取授信申请
            NlsCreditInfoVO nlsCreditInfoVO =
                    Optional.ofNullable(nlsCreditInfoService.queryByTransactionId(nlsApplyInfoVO.getBdTransactionId())).orElseGet(NlsCreditInfoVO::new);
            try {
                // 身份证正面字节流
                idpicture0 = getRemotePicture(nlsApplyInfoVO,basicInfo,ID_PICTURE0);//FileUtils.readFileToByteArray(new File("E://test.jpg"));
                // 获取身份证反面照片
                idpicture1 =  getRemotePicture(nlsApplyInfoVO,basicInfo,ID_PICTURE1);//FileUtils.readFileToByteArray(new File("E://test.jpg"));
                // 获取活体照照片
                livingPicture = getRemotePicture(nlsApplyInfoVO,basicInfo,ID_LIVING_PRITURE);//FileUtils.readFileToByteArray(new byte[]);
            } catch (ESBException e) {
                String msg = "=======>从百度获取文件出现异常:<======" + e;
                logger.error(msg, MSG_TEMPLATE);
                continue;
            }
            //将三个文件写入照片
            writeThreePictureToFile(idpicture0, idpicture1, livingPicture, nlsApplyInfoVO,nlsCreditInfoVO);
        }
    }

    /**
     * 将照片正面，反面，活体找信息写入磁盘 <br>
     * <p>
     * 0.1:caoxin:2019/3/25 14:12: 将照片正面，反面，活体找信息写入磁盘: <br>
     * 0.2:caoxin:2019/3/26 16:51: 增加事务: <br>
     *
     * @return
     * @author caoxin
     * @date 2019/3/25 14:12
     * @version 0.2
     * @since 2019/3/25 14:12
     */
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void writeThreePictureToFile(byte[] idpicture0, byte[] idpicture1, byte[] livingPicture, NlsApplyInfoVO nlsApplyInfoVO, NlsCreditInfoVO nlsCreditInfoVO) {
        // 授信申请流水号
        String lmtApplySeq = nlsCreditInfoVO.getLmtApplySeq();
        String msg = "=======>授信申请流水号为：" + nlsCreditInfoVO.getLmtApplySeq() + " 写入文件失败创建 身份证正面，反面，活体照文件失败<======";
        if (Objects.nonNull(idpicture0) && Objects.nonNull(idpicture1) && Objects.nonNull(livingPicture)) {
            // 产品ID
            String prdId = nlsCreditInfoVO.getPrdId();
            logger.debug("=======>【文件写入磁盘开始】....<======");
            String fileNameOfIDPICTURE0 = lmtApplySeq + ImageFileSeparator + FILE_SIGN_CERT_F + ImageFileSuffix;
            String fileNameOfIDPICTURE1 = lmtApplySeq + ImageFileSeparator + FILE_SIGN_CERT_B + ImageFileSuffix;
            String fileNameOfLIVINGPICTURE = lmtApplySeq + ImageFileSeparator + FILE_SIGN_FACE + ImageFileSuffix;
            // 创建文件夹
            String filePath = IMG_PATH +prdId+"/"+lmtApplySeq;
            File dirctory = new File(filePath);
            if (!dirctory.exists()) {
                dirctory.mkdirs();
            }
            // 创建文件
            File fileOfIDPicture0 = new File(filePath, fileNameOfIDPICTURE0);
            File fileOfIDPicture1 = new File(filePath, fileNameOfIDPICTURE1);
            File fileOfIDLivingPicture = new File(filePath, fileNameOfLIVINGPICTURE);

            // 覆盖原来的文件
            try {
                if (StringUtils.isEmpty(lmtApplySeq)){
                    logger.error("======================授信申请流水号为空!=====================");
                    return;
                }
                fileOfIDPicture0.createNewFile();
                fileOfIDPicture1.createNewFile();
                fileOfIDLivingPicture.createNewFile();

                //写入身份证正面并插入一条数据库记录
                FileUtils.writeByteArrayToFile(fileOfIDPicture0, idpicture0);
                insertInfoToBizDetail(filePath, fileNameOfIDPICTURE0, nlsCreditInfoVO, FILE_SIGN_CERT_F);

                // 写身份证反面照入文件并插入一条数据库记录
                FileUtils.writeByteArrayToFile(fileOfIDPicture1, idpicture1);
                insertInfoToBizDetail(filePath, fileNameOfIDPICTURE1, nlsCreditInfoVO, FILE_SIGN_CERT_B);

                // 写身份证活体照入文件并插入一条数据库记录
                FileUtils.writeByteArrayToFile(fileOfIDLivingPicture, livingPicture);
                insertInfoToBizDetail(filePath, fileNameOfLIVINGPICTURE, nlsCreditInfoVO, FILE_SIGN_FACE);

                // 插入ImageBizInfo
                insertInfoToBizInfo(nlsCreditInfoVO);

                // 更新放款申请信息照片信息为2（已获取）
                nlsApplyInfoVO.setBdIdpictureState(GET_PHOTO);
                nlsApplyInfoService.updateByPk(nlsApplyInfoVO);
                return;
            } catch (IOException e) {
                logger.error(msg, MSG_TEMPLATE);
                throw new RuntimeException("=======>照片写入文件出现异常！<======");
            } catch (ESBException e) {
                logger.error(e.getMessage(), MSG_TEMPLATE);
                throw new RuntimeException("=======>获取百度照片出现异常！<======");
            }catch (Exception e) {
                logger.error(e.getMessage());
                logger.error(msg, MSG_TEMPLATE);
                throw new RuntimeException("=======>更新网贷申请基本信息出现异常！<======");
            }
        } else {
            logger.error("=======>正面照片是不为空:<======"+Objects.nonNull(idpicture0));
            logger.error("=======>反面照片是不为空:<======"+Objects.nonNull(idpicture1));
            logger.error("=======>活体照片是不为空:<======"+Objects.nonNull(livingPicture));
            String errorMsg = "=======>获取的照片有空值写入失败!<======";
            logger.error(errorMsg, MSG_TEMPLATE);
        }
    }

    /**
     * 调用百度接口获取文件 <br>
     * <p>
     * 0.1:caoxin:2019/3/25 13:08: 调用百度接口获取文件: <br>
     * 0.2:caoxin:2019/3/28 13:08: 修改调用获取照片接口: <br>
     *
     * @return
     * @author caoxin
     * @date 2019/3/25 13:08
     * @version 0.1
     * @since 2019/3/25 13:08
     */

    private byte[] getRemotePicture(NlsApplyInfoVO nlsApplyInfoVO, DXMBasicInfo basicInfo, String pictureType) throws ESBException {
        // 设置照片的DataId
        ReqGetImageFileBean reqGetImageFileBean = new ReqGetImageFileBean();
        if (ID_PICTURE0.equals(pictureType)) {
            reqGetImageFileBean.setDataId(nlsApplyInfoVO.getBdIdpicture0());
        } else if (ID_PICTURE1.equals(pictureType)) {
            reqGetImageFileBean.setDataId(nlsApplyInfoVO.getBdIdpicture1());
        } else if (ID_LIVING_PRITURE.equals(pictureType)) {
            reqGetImageFileBean.setDataId(nlsApplyInfoVO.getBdLivingPhoto());
        }
        // 获取百度照片
        RespGetImageFileBean imageFileOfIDPicture = getImageFileService.getImageFile(reqGetImageFileBean,basicInfo, nlsApplyInfoVO);
        if (Objects.nonNull(imageFileOfIDPicture)) {
            String msg = "=======>成功获取百度响应对象<======";
            logger.debug(msg, MSG_TEMPLATE);
            return imageFileOfIDPicture.decodeBase64();
        }

        String msg = "=======>百度返回响应照片为空<======";
        logger.debug(msg, MSG_TEMPLATE);
        return null;
    }


    /**
     * 插入影像业务文件信息明细: <br>
     * <p>
     * 0.1:caoxin:2019/3/26 17:20: TODO: <br>
     *
     * @return
     * @author caoxin
     * @date 2019/3/26 17:20
     * @version 0.1
     * @since 2019/3/26 17:20
     */

    @Transactional(propagation = Propagation.MANDATORY)
    public void insertInfoToBizDetail(String filePath, String fileName, NlsCreditInfoVO nlsCreditInfoVO, String imageType) {
        // 初始化属性
        ImageBizDetailVO imageBizDetailVO = new ImageBizDetailVO();
        setInsertDefaultProperty(imageBizDetailVO);
        // 插入对应的值
        imageBizDetailVO.setApplySeq(nlsCreditInfoVO.getLmtApplySeq());
        imageBizDetailVO.setImageId(FileNameEnums.map.get(imageType));
        imageBizDetailVO.setImageType(FileNameEnums.map.get(imageType));
        imageBizDetailVO.setFileName(fileName);
        imageBizDetailVO.setFileDesc(nlsCreditInfoVO.getLmtApplySeq() + imageType);
        imageBizDetailVO.setFilePath(filePath + "/"+fileName);
        int i = imageBizDetailService.insertOrUpdateImageBizDetail(imageBizDetailVO);
        if (i == -1) {
            throw new RuntimeException("=======>插入影像业务文件信息明细出错<======");
        }
    }

    /**
     * 插入影像业务信息 <br>
     * <p>
     * 0.1:caoxin:2019/3/26 17:19: 插入影像业务信息: <br>
     *
     * @return
     * @author caoxin
     * @date 2019/3/26 17:19
     * @version 0.1
     * @since 2019/3/26 17:19
     */

    @Transactional(propagation = Propagation.MANDATORY)
    public void insertInfoToBizInfo(NlsCreditInfoVO nlsCreditInfoVO) {
    	 // 初始化的属性
        ImageBizInfoVO imageBizInfoVO = new ImageBizInfoVO();
        //setInsertDefaultProperty(imageBizInfoVO);
        // 设置对应属性
        imageBizInfoVO.setApplySeq(nlsCreditInfoVO.getLmtApplySeq());
        imageBizInfoVO.setPrdId(nlsCreditInfoVO.getPrdId());
        imageBizInfoVO.setPrdCode(nlsCreditInfoVO.getPrdCode());
        imageBizInfoVO.setPrdName(nlsCreditInfoVO.getPrdName());
        imageBizInfoVO.setCusId(nlsCreditInfoVO.getCusId());
        imageBizInfoVO.setCusName(nlsCreditInfoVO.getCusName());
        imageBizInfoVO.setSoltImageAccept(ImageBizConstant.YesNoEnum.YES.VALUE);
        int bizInfoNum = 0;
		ImageBizInfoVO queryImageBizInfoVO = imageBizInfoService.queryByPk(imageBizInfoVO);
        if (queryImageBizInfoVO != null) {
			// SoltImageAccept 更新、追加
			imageBizInfoVO.setSoltImageAccept("2");
			imageBizInfoVO.setLastModifyTime(TimeUtil.getCurrentDateTime());
			bizInfoNum = imageBizInfoService.updateByPk(imageBizInfoVO);
		} else {
            imageBizInfoVO.setCreateTime(TimeUtil.getCurrentDateTime());
			bizInfoNum = imageBizInfoService.insertImageBizInfo(imageBizInfoVO);
		}
        if (bizInfoNum == -1) {
            throw new RuntimeException("=======>插入影像业务文件信息出错<======");
        }
    }


}